package com.apes.fn.business.insurance.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apes.fn.business.insurance.modle.InsuranceOrder;
import com.apes.fn.business.insurance.modle.InsuranceReport;
import com.apes.fn.business.insurance.repository.InsuranceOrderRepository;
import com.apes.fn.business.insurance.repository.InsuranceReportDao;
import com.apes.fn.business.insurance.repository.InsuranceReportRepository;
import com.apes.framework.api.DomainService;
import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.util.Arith;
import com.apes.framework.util.DateUtil;
import com.apes.framework.util.MapUtil;
import com.apes.hr.base.model.Employee;
import com.apes.hr.base.repository.EmployeeRepository;
import com.apes.scm.masterdata.finance.service.CrossICService;
import com.apes.scm.masterdata.frame.model.Dept;
import com.apes.scm.masterdata.frame.repository.StoreRepository;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.rbac.model.Post;
import com.apes.scm.rbac.repository.PostRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import java.text.DecimalFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @program: apes-server
 * @description
 * @author: czs
 * @create: 2021-08-18 16:53
 **/
@Service("insuranceReportService")
public class InsuranceReportService extends DomainService {

    @Autowired
    private InsuranceReportRepository insuranceReportRepository;

    @Autowired
    private InsuranceReportDao insuranceReportDao;

    @Autowired
    private InsuranceOrderRepository insuranceOrderRepository;

    @Autowired
    private EmployeeRepository employeeRepository;

    @Autowired
    private StoreRepository storeRepository;

    @Autowired
    private PostRepository postRepository;



    private Map<String, List<InsuranceOrder>> abolishDateInsuranceOrderCollect;

    /**
     * 查询
     * @param request
     * @return
     */
    public Object findAll(SimpleRequest request){
        Map condition = parseCondition(request);
        boolean type = condition.get("salesmanShowType") != null;
        String statisticType = type?"salesman":"dept";

        String show_type = type?(String)condition.get("salesmanShowType"):(String)condition.get("deptShowType");
        if (show_type==null)throw new RuntimeException("未知类型");
        Date start = (Date) condition.get("CALCULATE_DATE_START");
        Date end = (Date) condition.get("CALCULATE_DATE_END");
        if ("1".equals(show_type)){
            JSONObject startAndEndDate = findStartAndEndDate(start, end);
            start=startAndEndDate.getDate("start");
            end=startAndEndDate.getDate("end");
        }else if ("2".equals(show_type)){//汇总字段
            start=null;
            end=null;
        }
        JSONArray array = condition.get("dept")==null?new JSONArray():(JSONArray) condition.get("dept");
        String postId = getPostId(request);
        Post post = postRepository.findOne(postId);
        Dept dept = post.getDept();
        if (dept!=null)array.add(dept.getId());
        if (array.size()==0)array=null;
        List<InsuranceReport> reports = insuranceReportRepository.findAll(
                JpaDsl.toCriteriaIgnoreNull(
                        "dept.id", "IN", array,
                        "salesman.id", "IN", condition.get("salesman"),
                        "dept.company.party.corporate.operation.id", "EQ", condition.get("operation"),
                        "post.id", "IN", condition.get("workPost"),
                        "store.address", "LIKE", condition.get("area"),
                        "store.county.name", "LIKE", condition.get("county"),
                        "store.zyzfn", "EQ", condition.get("zyzfn"),
                        "statisticType", "EQ", statisticType,
                        "statisticDate", "GTE", start,
                        "statisticDate", "LTE", end,
                        "store.openDay", "GTE", condition.get("OPEN_DAY_START"),
                        "store.openDay", "LTE", condition.get("OPEN_DAY_END")
                )
        );


        JSONArray jsonArray = returnToWeb(reports, show_type,statisticType);
        PageImpl statisticDate = SpringManager.getBean(CrossICService.class).pageInfo(request.getJO(), jsonArray, new Sort(Sort.Direction.ASC, "statisticDate", statisticType));

        Map result = MapUtil.mapped(statisticDate);
        Map<String,Double> footer = new HashMap();
        List<String> sumList = Arrays.asList(
                "qtyOrder","priceDate","qtyMonthOrder",
                "priceMonth","qtyConcurrentYearOrder",
                "priceConcurrentYear","qtyConcurrentMonthOrder",
                "todaySalesCommission","monthSalesCommission",
                "priceConcurrentMonth");
        for (String s : sumList) {
            double sum = 0;
            for (Object o : jsonArray) {
                JSONObject jsonObject = (JSONObject) o;
                double doubleValue = jsonObject.getDoubleValue(s);
                sum+=doubleValue;
            }
            footer.put(s, Arith.round(sum,2));
        }

        result.put("footer",Arrays.asList(footer));
        result.put("gridheader",null);
        return result;

    }

    /**
     * 日结测试
     * @param request
     * @return
     */
    public String insuranceDailySettlementTest(SimpleRequest request) {
        JSONObject requestJO = request.getJO();
        Date startDate = requestJO.getDate("startDate");
        Date endDate = requestJO.getDate("endDate");

        while (startDate.before(endDate)) {

            Date add = DateUtil.add(startDate, Calendar.DATE, 1);
            Date date = new Date();
            date.setTime(add.getTime()-1);
            String s = dailySettlement(startDate, date);
            System.out.println("----------------------------------"+s+"--------------------------------");
            startDate = add;
        }

        return "success";
    }


    /**
     * 处理返回前端的数据
     * @param reports
     * @param show_type
     * @return
     */
    private JSONArray returnToWeb(List<InsuranceReport> reports, String show_type,String groupingType){
        JSONArray resultList = new JSONArray();
        Map<Object, List<InsuranceReport>> collect = getGroupingType(reports,show_type,groupingType);

        for (Object o : collect.keySet()) {
            List<InsuranceReport> insuranceReports = collect.get(o);
            InsuranceReport insuranceReport = insuranceReports.stream().sorted(Comparator.comparing(InsuranceReport::getStatisticDate).reversed()).findFirst().get();
            JSONObject reusltJson = new JSONObject();
            String date = "1".equals(show_type) ? DateUtil.format(insuranceReport.getStatisticDateMonth(), DateUtil.SHOW_MONTH_FORMAT) : DateUtil.format(insuranceReport.getStatisticDate(), DateUtil.SHOW_DATE_FORMAT);
            Date sortDate = "1".equals(show_type) ? insuranceReport.getStatisticDateMonth() : insuranceReport.getStatisticDate();
            if (!"2".equals(show_type))reusltJson.put("statisticDate",date);
            reusltJson.put("sortDate",sortDate);
            mergeReportData(insuranceReports,reusltJson,insuranceReport,show_type);
            resultList.add(reusltJson);
        }
        resultList = resultList.stream().sorted(Comparator.comparing(result -> ((JSONObject)result).getDate("sortDate")).reversed()).collect(Collectors.toCollection(JSONArray::new));
        return resultList;

    }

    private Map<Object, List<InsuranceReport>> getGroupingType(List<InsuranceReport> reports, String show_type,String groupingType){
        Map<Object, List<InsuranceReport>> collect = new HashMap<>();
        if ("salesman".equals(groupingType)){
            if ("0".equals(show_type)){
                collect = reports.stream().collect(Collectors.groupingBy(report -> report.getId()));
            }else if ("1".equals(show_type)){
                collect = reports.stream().collect(Collectors.groupingBy(report -> {
                    return report.getStatisticDateMonth()+report.getSalesman().getName();
                }));
            }else if ("2".equals(show_type)){
                collect = reports.stream().collect(Collectors.groupingBy(report -> report.getSalesman().getId()));
            }
        }
        if ("dept".equals(groupingType)){
            if ("0".equals(show_type)){
                collect = reports.stream().collect(Collectors.groupingBy(report -> report.getStatisticDate()+report.getDept().getId()));
            }else if ("1".equals(show_type)){
                collect = reports.stream().collect(Collectors.groupingBy(report -> report.getStatisticDateMonth()+report.getDept().getId()));
            }else if ("2".equals(show_type)){
                collect = reports.stream().collect(Collectors.groupingBy(report -> report.getDept().getId()));
            }
        }
        return collect;
    }


    /**
     * 合并数据返回前端
     * @param insuranceReports
     * @param resultJson
     */
    private void mergeReportData(List<InsuranceReport> insuranceReports,JSONObject resultJson,InsuranceReport report,String show_type){
        DecimalFormat df   = new DecimalFormat("######0.00");
        double orderQty = 0;
        double toDayPrice = 0;
        double qtyConcurrentMonthOrder = 0;
        double priceConcurrentMonth = 0;
        double qtyConcurrentYearOrder = 0;
        double priceConcurrentYear = 0;
        double todaySalesCommission = 0;
        double monthSalesCommission = 0;
        double priceMonth = 0;
        boolean all = show_type.equals("0");
        for (InsuranceReport insuranceReport : insuranceReports) {
            orderQty +=insuranceReport.getQtyOrder();
            toDayPrice += insuranceReport.getPriceDate();
            if (all){
                qtyConcurrentMonthOrder += insuranceReport.getQtyConcurrentMonthOrder();
                priceConcurrentMonth += insuranceReport.getPriceConcurrentMonth();
                qtyConcurrentYearOrder += insuranceReport.getQtyConcurrentYearOrder();
                priceConcurrentYear += insuranceReport.getPriceConcurrentYear();
                todaySalesCommission += insuranceReport.getTodaySalesCommission();
                monthSalesCommission += insuranceReport.getMonthSalesCommission();
                priceMonth += insuranceReport.getPriceMonth();
            }else {
                qtyConcurrentMonthOrder = report.getQtyConcurrentMonthOrder();
                priceConcurrentMonth = report.getPriceConcurrentMonth();
                qtyConcurrentYearOrder = report.getQtyConcurrentYearOrder();
                priceConcurrentYear = report.getPriceConcurrentYear();
                todaySalesCommission = report.getTodaySalesCommission();
                monthSalesCommission = report.getMonthSalesCommission();
                priceMonth = toDayPrice;
            }

        }
        if (report.getStatisticType().equals("salesman")){
            resultJson.put("salesman",report.getSalesman().getName());
            resultJson.put("salesmanId",report.getSalesman().getId());
            if (report.getPost()!=null)resultJson.put("post",report.getPost().getName());
        }
        resultJson.put("deptId",report.getDept().getId());
        resultJson.put("dept",report.getDept().getName());
        resultJson.put("operationName",report.getDept().getCompany().getParty().getCorporate().getOperation().getDescription());
        resultJson.put("zyzfn",report.getStore().isZyzfn()?"是":"否");
        resultJson.put("qtyOrder",orderQty);
        resultJson.put("priceDate",toDayPrice);
        resultJson.put("qtyMonthOrder",all?report.getQtyMonthOrder():orderQty);
        resultJson.put("priceMonth",priceMonth);
        resultJson.put("qtyConcurrentYearOrder",Arith.round(qtyConcurrentYearOrder,2));
        resultJson.put("priceConcurrentYear",Arith.round(priceConcurrentYear,2));
        resultJson.put("orderYearOnYear",Arith.round((qtyConcurrentYearOrder==0?1:(orderQty-qtyConcurrentYearOrder)/ qtyConcurrentYearOrder)*100,2)+"%");
        resultJson.put("priceYearOnYear",Arith.round((priceConcurrentYear==0?1:(toDayPrice-priceConcurrentYear)/ priceConcurrentYear)*100,2)+"%");
        resultJson.put("qtyConcurrentMonthOrder",Arith.round(qtyConcurrentMonthOrder,2));
        resultJson.put("priceConcurrentMonth",Arith.round(priceConcurrentMonth,2));
        resultJson.put("orderChainIndex",Arith.round((qtyConcurrentMonthOrder==0?1:(orderQty-qtyConcurrentMonthOrder)/ qtyConcurrentMonthOrder)*100,2)+"%");
        resultJson.put("priceChainIndex",Arith.round((priceConcurrentMonth==0?1:(toDayPrice-priceConcurrentMonth)/ priceConcurrentMonth)*100,2)+"%");
        resultJson.put("todaySalesCommission",Arith.round(todaySalesCommission,2));
        resultJson.put("monthSalesCommission",Arith.round(monthSalesCommission,2));
        Date openDay = report.getStore().getOpenDay();
        if(openDay!=null)resultJson.put("openDate",DateUtil.format(openDay,DateUtil.SHOW_DATE_FORMAT));
        resultJson.put("area",report.getStore().getCity().getName());
        resultJson.put("county",report.getStore().getCounty().getName());
    }

    /***
     * 解析条件
     */
    private Map parseCondition(SimpleRequest request) {
        JSONArray condition = request.getJO().getJSONArray("condition");
        Map returnMap = new HashMap();
        condition.stream().forEach(json -> {
            JSONObject obj = (JSONObject) json;

            if (obj.getString("type") == null) {
                returnMap.put(obj.getString("field"), obj.getString("value"));
                if (obj.getString("operator")!=null&&obj.getString("operator").equals("IN")) {
                    JSONArray value = obj.getJSONArray("value");

                    returnMap.put(obj.getString("field"),value);
                }
                if (obj.getString("field").equals("zyzfn")){
                    switch (obj.getString("value")){
                        case "1":
                            returnMap.put(obj.getString("field"),true);
                            break;
                        case "2":
                            returnMap.put(obj.getString("field"),false);
                            break;
                    }
                }
            } else if (obj.getString("type").equals("date") && obj.getString("operator").equals("GTE")) {
                returnMap.put(obj.getString("field") + "_START", DateUtil.parse(obj.getString("value"), DateUtil.SHOW_DATETIME_FORMAT));
            } else if (obj.getString("type").equals("date") && obj.getString("operator").equals("LTE")) {
                returnMap.put(obj.getString("field") + "_END", DateUtil.parse(obj.getString("value"), DateUtil.SHOW_DATETIME_FORMAT));
            } else if (obj.getString("type").equals("date") && obj.getString("operator").equals("EQ")) {
                returnMap.put(obj.getString("field"), DateUtil.parse(obj.getString("value")));
            }
        });
        return returnMap;
    }


    /**
     * 日结人员车险订单
     */
    public String insuranceDailySettlement(SimpleRequest request){
        Date date = new Date();
        Date startTemp = DateUtil.parse(DateUtil.format(date, DateUtil.SHOW_DATE_FORMAT), DateUtil.SHOW_DATE_FORMAT);
        Date start = DateUtil.parse(DateUtil.timeStampToStr(startTemp.getTime()-86400000L), DateUtil.SHOW_DATE_FORMAT);
        Date end = DateUtil.parse(DateUtil.timeStampToStr(startTemp.getTime()), DateUtil.SHOW_DATE_FORMAT);
        return dailySettlement(start,end);
    }

    private String dailySettlement(Date start, Date end) {
        List<InsuranceReport> all = insuranceReportRepository.findAll(JpaDsl.toCriteriaIgnoreNull(
                "statisticDate", "EQ", start
        ));
        if (all.size()!=0)return DateUtil.format(start, DateUtil.SHOW_DATE_FORMAT)+"已日结,请勿重复日结";
        List<InsuranceOrder> receiptInsuranceOrder = insuranceOrderRepository.findAll(JpaDsl.toCriteriaIgnoreNull(
                "createDate", "GTE", start,
                "createDate", "LTE", end
        ));
        List<InsuranceOrder> refundInsuranceOrder = insuranceOrderRepository.findAll(JpaDsl.toCriteriaIgnoreNull(
                "refundDate", "GTE", start,
                "refundDate", "LTE", end
        ));
        List<InsuranceOrder> abolishDateInsuranceOrder = insuranceOrderRepository.findAll(JpaDsl.toCriteriaIgnoreNull(
                "abolishDate", "GTE", start,
                "abolishDate", "LTE", end
        ));
        //日结人员
        Map<String, List<InsuranceOrder>> receiptInsuranceOrderCollect = receiptInsuranceOrder.stream().filter(insuranceOrder -> insuranceOrder.getCommercialInsurance()+insuranceOrder.getCompulsoryInsurance()>0).collect(Collectors.groupingBy(insuranceOrder -> insuranceOrder.getSalesman().getName()));
        Map<String, List<InsuranceOrder>> refundInsuranceOrderCollect = refundInsuranceOrder.stream().filter(insuranceOrder -> insuranceOrder.getCommercialInsurance()+insuranceOrder.getCompulsoryInsurance()>0).collect(Collectors.groupingBy(insuranceOrder -> insuranceOrder.getSalesman().getName()));
        abolishDateInsuranceOrderCollect = abolishDateInsuranceOrder.stream().collect(Collectors.groupingBy(insuranceOrder -> insuranceOrder.getSalesman().getName()));
        saveInsuranceReport(receiptInsuranceOrderCollect,refundInsuranceOrderCollect,start,"salesman");
        //日结门店
        receiptInsuranceOrderCollect = receiptInsuranceOrder.stream().filter(insuranceOrder -> insuranceOrder.getCommercialInsurance()+insuranceOrder.getCompulsoryInsurance()>0).collect(Collectors.groupingBy(insuranceOrder -> insuranceOrder.getDept().getName()));
        refundInsuranceOrderCollect = refundInsuranceOrder.stream().filter(insuranceOrder -> insuranceOrder.getCommercialInsurance()+insuranceOrder.getCompulsoryInsurance()>0).collect(Collectors.groupingBy(insuranceOrder -> insuranceOrder.getDept().getName()));
        abolishDateInsuranceOrderCollect = abolishDateInsuranceOrder.stream().collect(Collectors.groupingBy(insuranceOrder -> insuranceOrder.getDept().getName()));
        saveInsuranceReport(receiptInsuranceOrderCollect,refundInsuranceOrderCollect,start,"dept");


        return DateUtil.format(start, DateUtil.SHOW_DATE_FORMAT)+" 收款单数:"+receiptInsuranceOrder.size()+",退款单数:"+refundInsuranceOrder.size();
    }

    private void saveInsuranceReport(Map<String, List<InsuranceOrder>> receiptInsuranceOrderCollect,
                                Map<String, List<InsuranceOrder>> refundInsuranceOrderCollect,
                                Date start, String statisticType
            ){
        for (String s : receiptInsuranceOrderCollect.keySet()) {
            List<InsuranceOrder> orders = receiptInsuranceOrderCollect.get(s)==null?new ArrayList<>():receiptInsuranceOrderCollect.get(s);
            List<InsuranceOrder> refund = refundInsuranceOrderCollect.get(s)==null?new ArrayList<>():refundInsuranceOrderCollect.get(s);
            List<InsuranceOrder> abolish = abolishDateInsuranceOrderCollect.get(s)==null?new ArrayList<>():abolishDateInsuranceOrderCollect.get(s);
            InsuranceOrder insuranceOrder = orders.get(0);
            if (!refund.isEmpty())refundInsuranceOrderCollect.remove(s);
            if (!abolish.isEmpty())abolishDateInsuranceOrderCollect.remove(s);
            InsuranceReport report = getInsuranceReport(orders, refund,abolish,start,insuranceOrder,statisticType);
            insuranceReportRepository.save(report);
        }
        for (String s : refundInsuranceOrderCollect.keySet()) {
            List<InsuranceOrder> orders = receiptInsuranceOrderCollect.get(s)==null?new ArrayList<>():receiptInsuranceOrderCollect.get(s);
            List<InsuranceOrder> refund = refundInsuranceOrderCollect.get(s)==null?new ArrayList<>():refundInsuranceOrderCollect.get(s);
            List<InsuranceOrder> abolish = abolishDateInsuranceOrderCollect.get(s)==null?new ArrayList<>():abolishDateInsuranceOrderCollect.get(s);
            InsuranceOrder insuranceOrder = refund.get(0);
            if (!abolishDateInsuranceOrderCollect.isEmpty())abolish = abolishDateInsuranceOrderCollect.remove(s);
            InsuranceReport report = getInsuranceReport(orders, refund, abolish, start,insuranceOrder,statisticType);
            insuranceReportRepository.save(report);
        }
        for (String s : abolishDateInsuranceOrderCollect.keySet()) {
            List<InsuranceOrder> orders = receiptInsuranceOrderCollect.get(s)==null?new ArrayList<>():receiptInsuranceOrderCollect.get(s);
            List<InsuranceOrder> refund = refundInsuranceOrderCollect.get(s)==null?new ArrayList<>():refundInsuranceOrderCollect.get(s);
            List<InsuranceOrder> abolish = abolishDateInsuranceOrderCollect.get(s)==null?new ArrayList<>():abolishDateInsuranceOrderCollect.get(s);
            InsuranceOrder insuranceOrder = abolish.get(0);
            InsuranceReport report = getInsuranceReport(orders, refund, abolish, start,insuranceOrder,statisticType);
            insuranceReportRepository.save(report);
        }
    }


    /**
     * 封装日结数据
     * @param orders
     * @param refund
     * @param abolish
     * @param start
     * @param insuranceOrder
     * @return
     */
    private InsuranceReport getInsuranceReport(List<InsuranceOrder> orders, List<InsuranceOrder> refund,
                                               List<InsuranceOrder> abolish, Date start, InsuranceOrder insuranceOrder, String statisticType){
        InsuranceReport report = new InsuranceReport();
        report.setDept(insuranceOrder.getDept());
        if (statisticType.equals("salesman")){
            report.setSalesman(insuranceOrder.getSalesman());
            Employee employee = employeeRepository.findByParty(insuranceOrder.getSalesman().getParty());
            if (employee!=null)report.setPost(employee.getPost());

        }
        report.setStore(storeRepository.findByDept(insuranceOrder.getDept()));
        report.setPriceDate(getPriceTatal(orders,refund,abolish));
        report.setQtyOrder(orders.size());
        report.setStatisticDate(start);
        getConcurrent(start,report,statisticType);
        insuranceMonthData(start,report,statisticType);
        getSalesCommission(start,report,statisticType);

        if (refund!=null){
            report.setQtyOrder(report.getQtyOrder()-refund.size());
            orders.addAll(refund);
        }
        getRate(report);
        report.setStatisticType(statisticType);
        return report;

    }

    /**
     * 计算比率
     * @param report
     */
    private void getRate(InsuranceReport report){
        //计算同比
        report.setOrderYearOnYear(report.getQtyConcurrentYearOrder()==0?1:(report.getQtyOrder()-report.getQtyConcurrentYearOrder())/report.getQtyConcurrentYearOrder());
        report.setPriceYearOnYear(report.getPriceConcurrentYear()==0?1:(report.getPriceDate()-report.getPriceConcurrentYear())/report.getPriceConcurrentYear());
        //计算环比
        report.setOrderChainIndex(report.getQtyMonthOrder()==0?1:(report.getQtyOrder()-report.getQtyMonthOrder())/report.getQtyMonthOrder());
        report.setPriceChainIndex(report.getPriceConcurrentMonth()==0?1:(report.getPriceDate()-report.getPriceConcurrentMonth())/report.getPriceConcurrentMonth());
    }

    /**
     * 获取提成
     * @param date
     * @param report
     */
    private void getSalesCommission(Date date,InsuranceReport report,String statisticType){
        getSalesCommission( date, report,Calendar.MONTH,statisticType);
        getSalesCommission( date, report,Calendar.DATE,statisticType);
    }

    /**
     * 获取天/月提成
     * @param date
     * @param report
     * @param dateType
     */
    private void getSalesCommission(Date date,InsuranceReport report,int dateType,String statisticType){
        JSONObject parm = new JSONObject();
        parm.put("date","DD");
        if (statisticType.equals("salesman")){
            parm.put("sales",report.getSalesman().getId());
        }else if (statisticType.equals("dept")){
            parm.put("sales",report.getDept().getId());
        }

        parm.putAll(findStartAndEndDate(date,dateType,false));
        if (dateType==Calendar.MONTH)parm.put("date","MM");
        JSONArray insuranceCommission = statisticType.equals("salesman")?insuranceReportDao.findInsuranceCommission(parm):insuranceReportDao.findDeptInsuranceCommission(parm);
        JSONObject result = (JSONObject) insuranceCommission.get(0);
        double profit = result.getDoubleValue("FN_PROFIT");
        if (dateType==Calendar.DATE){
            report.setTodaySalesCommission(profit);
        } else if (dateType==Calendar.MONTH) {
            report.setMonthSalesCommission(profit);
        }
    }

    /**
     * 车险报表月数据
     * @param date
     * @param report
     */
    private void insuranceMonthData(Date date,InsuranceReport report,String statisticType){
        JSONObject startAndEndDate = findStartAndEndDate(date, Calendar.MONTH,false);
        JSONObject orderAndPrice = statisticType.equals("salesman")?findOrderAndPrice(report.getSalesman(), startAndEndDate.getDate("start"), startAndEndDate.getDate("end"))
                :findOrderAndPrice(report.getDept(), startAndEndDate.getDate("start"), startAndEndDate.getDate("end"));
        report.setQtyMonthOrder(orderAndPrice.getDoubleValue("order"));
        report.setPriceMonth(orderAndPrice.getDoubleValue("price"));

    }

    /**
     * 获取年月日结
     * @param start
     * @param report
     */
    private void getConcurrent(Date start,InsuranceReport report,String statisticType){
        getConcurrent(start,report,Calendar.MONTH,statisticType);
        getConcurrent(start,report,Calendar.YEAR,statisticType);
    }

    /**
     * 获取上月/年同期数据
     * @param start 日结时间
     * @param report
     * @param dateType
     */
    private void getConcurrent(Date start,InsuranceReport report,int dateType,String statisticType){
        JSONObject startAndEndDate = findStartAndEndDate(start, dateType,true);
        JSONObject orderAndPrice = statisticType.equals("salesman")?findOrderAndPrice(report.getSalesman(), startAndEndDate.getDate("start"), startAndEndDate.getDate("end"))
                :findOrderAndPrice(report.getDept(), startAndEndDate.getDate("start"), startAndEndDate.getDate("end"));
        if (dateType==Calendar.MONTH){
            report.setQtyConcurrentMonthOrder(orderAndPrice.getDoubleValue("order"));
            report.setPriceConcurrentMonth(orderAndPrice.getDoubleValue("price"));
        }else if (dateType==Calendar.YEAR){
            report.setQtyConcurrentYearOrder(orderAndPrice.getDoubleValue("order"));
            report.setPriceConcurrentYear(orderAndPrice.getDoubleValue("price"));
        }else {
            throw new RuntimeException("无效类型:"+dateType);
        }
    }


    /**
     * 计算单量/保费
     * @param receiptInsuranceOrder
     * @param refundInsuranceOrder
     * @return
     */
    private double getPriceTatal(List<InsuranceOrder> receiptInsuranceOrder,List<InsuranceOrder> refundInsuranceOrder,List<InsuranceOrder> abolishDateInsuranceOrder){
        Double price = 0.0;
        Double refund = 0.0;
        Double abolish = 0.0;

        if (receiptInsuranceOrder!=null&&!receiptInsuranceOrder.isEmpty())
            price = receiptInsuranceOrder.stream().mapToDouble(InsuranceOrder::getCommercialInsurance).sum()+receiptInsuranceOrder.stream().mapToDouble(InsuranceOrder::getCompulsoryInsurance).sum();

        if (abolishDateInsuranceOrder!=null&&!abolishDateInsuranceOrder.isEmpty())
            abolish = abolishDateInsuranceOrder.stream().mapToDouble(InsuranceOrder::getAbolishAmount).sum();

        if (refundInsuranceOrder!=null&&!refundInsuranceOrder.isEmpty())
            refund = refundInsuranceOrder.stream().mapToDouble(InsuranceOrder::getCommercialInsurance).sum()+refundInsuranceOrder.stream().mapToDouble(InsuranceOrder::getCompulsoryInsurance).sum();

        return price-refund-abolish;
    }

    /**
     * 获取车险单
     * @param salesman
     * @param start
     * @param end
     * @return
     */
    private JSONObject findOrderAndPrice(PartyRole salesman,Date start,Date end){
        JSONObject result = new JSONObject();
        List<InsuranceOrder> receiptInsuranceOrder = insuranceOrderRepository.findAll(JpaDsl.toCriteriaIgnoreNull(
                "salesman","EQ",salesman,
                "receiptDate", "GTE", start,
                "receiptDate", "LTE", end
        ));
        List<InsuranceOrder> refundInsuranceOrder = insuranceOrderRepository.findAll(JpaDsl.toCriteriaIgnoreNull(
                "salesman","EQ",salesman,
                "refundDate", "GTE", start,
                "refundDate", "LTE", end
        ));
        List<InsuranceOrder> abolishDateInsuranceOrder = insuranceOrderRepository.findAll(JpaDsl.toCriteriaIgnoreNull(
                "salesman","EQ",salesman,
                "abolishDate", "GTE", start,
                "abolishDate", "LTE", end
        ));
        result.put("order",receiptInsuranceOrder.size()-refundInsuranceOrder.size());
        result.put("price",getPriceTatal(receiptInsuranceOrder,refundInsuranceOrder,abolishDateInsuranceOrder));
        return result;
    }
    private JSONObject findOrderAndPrice(Dept dept, Date start, Date end){
        JSONObject result = new JSONObject();
        List<InsuranceOrder> receiptInsuranceOrder = insuranceOrderRepository.findAll(JpaDsl.toCriteriaIgnoreNull(
                "dept","EQ",dept,
                "createDate", "GTE", start,
                "createDate", "LTE", end
        )).stream().filter(insuranceOrder -> insuranceOrder.getCommercialInsurance()+insuranceOrder.getCompulsoryInsurance()>0).collect(Collectors.toList());
        List<InsuranceOrder> refundInsuranceOrder = insuranceOrderRepository.findAll(JpaDsl.toCriteriaIgnoreNull(
                "dept","EQ",dept,
                "refundDate", "GTE", start,
                "refundDate", "LTE", end
        )).stream().filter(insuranceOrder -> insuranceOrder.getCommercialInsurance()+insuranceOrder.getCompulsoryInsurance()>0).collect(Collectors.toList());;
        List<InsuranceOrder> abolishDateInsuranceOrder = insuranceOrderRepository.findAll(JpaDsl.toCriteriaIgnoreNull(
                "dept","EQ",dept,
                "abolishDate", "GTE", start,
                "abolishDate", "LTE", end
        ));
        result.put("order",receiptInsuranceOrder.size()-refundInsuranceOrder.size());
        result.put("price",getPriceTatal(receiptInsuranceOrder,refundInsuranceOrder,abolishDateInsuranceOrder));
        return result;
    }

    /**
     * 获取开始结束日期
     * @param date
     * @param dateType
     * @return
     */
    private JSONObject findStartAndEndDate(Date date,int dateType,Boolean last){

        JSONObject result = new JSONObject();
        Date start =new Date();
        Date end = new Date();
        if (last){
            if (date==null){
                start = DateUtil.parse("2000-01-01",DateUtil.SHOW_DATE_FORMAT);
                end = new Date();
            }else if (dateType==Calendar.MONTH){
                end = DateUtil.parse(DateUtil.format(date, DateUtil.SHOW_MONTH_FORMAT), DateUtil.SHOW_MONTH_FORMAT);
                start = DateUtil.parse(DateUtil.format(new Date(end.getTime()-1000), DateUtil.SHOW_MONTH_FORMAT), DateUtil.SHOW_MONTH_FORMAT);
            }else if (dateType==Calendar.DATE){
                end = DateUtil.parse(DateUtil.format(date, DateUtil.SHOW_DATE_FORMAT), DateUtil.SHOW_DATE_FORMAT);
                start = DateUtil.parse(DateUtil.format(new Date(end.getTime()-1000), DateUtil.SHOW_DATE_FORMAT), DateUtil.SHOW_DATE_FORMAT);
            }else if (dateType==Calendar.YEAR){
                start = DateUtil.parse(DateUtil.format(date, DateUtil.SHOW_DATE_FORMAT), DateUtil.SHOW_DATE_FORMAT);
                Calendar nextMonth = Calendar.getInstance();
                nextMonth.setTime(start);
                nextMonth.add(dateType,-1);
                end = new Date(nextMonth.getTime().getTime()-1000);
                start = DateUtil.parse(DateUtil.format(end, DateUtil.SHOW_DATE_FORMAT), DateUtil.SHOW_DATE_FORMAT);
            }else {
                throw new RuntimeException("未知类型");
            }
        }else {
            if (date==null){
                start = DateUtil.parse("2000-01-01",DateUtil.SHOW_DATE_FORMAT);
                end = new Date();
            }else if (dateType==Calendar.MONTH){
                start = DateUtil.parse(DateUtil.format(date, DateUtil.SHOW_MONTH_FORMAT), DateUtil.SHOW_MONTH_FORMAT);
                Calendar nextMonth = Calendar.getInstance();
                nextMonth.setTime(start);
                nextMonth.add(dateType,1);
                end = new Date(nextMonth.getTime().getTime()-1000);
            }else if (dateType==Calendar.DATE){
                start = DateUtil.parse(DateUtil.format(date, DateUtil.SHOW_DATE_FORMAT), DateUtil.SHOW_DATE_FORMAT);
                Calendar nextMonth = Calendar.getInstance();
                nextMonth.setTime(start);
                nextMonth.add(dateType,1);
                end = new Date(nextMonth.getTime().getTime()-1000);
            }else if (dateType==Calendar.YEAR){
                start = DateUtil.parse(DateUtil.format(date, "yyyy"), "yyyy");
                Calendar nextMonth = Calendar.getInstance();
                nextMonth.setTime(start);
                nextMonth.add(dateType,1);
                end = new Date(nextMonth.getTime().getTime()-1000);
            }else {
                throw new RuntimeException("未知类型");
            }
        }
        result.put("start",start);
        result.put("end",end);
        return result;
    }




    private JSONObject findStartAndEndDate(Date start,Date end){
        if (start==null){
            start = DateUtil.parse("2000-01-01",DateUtil.SHOW_DATE_FORMAT);
            end = new Date();
        }
        start = DateUtil.parse(DateUtil.format(start, DateUtil.SHOW_MONTH_FORMAT), DateUtil.SHOW_MONTH_FORMAT);
        end = DateUtil.parse(DateUtil.format(end, DateUtil.SHOW_MONTH_FORMAT), DateUtil.SHOW_MONTH_FORMAT);
        Calendar nextMonth = Calendar.getInstance();
        nextMonth.setTime(end);
        nextMonth.add(Calendar.MONTH,1);
        end = new Date(nextMonth.getTime().getTime()-1000);
        JSONObject result = new JSONObject();
        result.put("start",start);
        result.put("end",end);
        return result;
    }
}
